﻿using KinonekoSoftware.Extensions.Collections;

namespace KinonekoSoftware.CodariaDB.IO
{
    public static class ResourceManager
    {
        private static readonly List<ResourceFinder> _Finders;

        static ResourceManager()
        {
            _Finders = new List<ResourceFinder>();
            Finders  = new ReadOnlyCollection<ResourceFinder>(_Finders);

            Initialize();
        }

        static void Initialize()
        {
            _Finders.Add(new InstanceCacheResourceFinder());
            _Finders.Add(new DataPartPictureFinder());
            _Finders.Add(new TalkingEmojiResourceFinder());
        }

        public static Task<List<Resource>> Find(IRepository repository)
        {
            return Task.Run<List<Resource>>(() =>
            {
                var findResult = new List<Resource>(512);

                foreach (var finder in _Finders)
                {
                    finder.GetResources(findResult, repository);
                }


                return findResult;
            });
        }

        public static Task<List<Resource>> FindDirtyUsage(RepositoryRuntime repository)
        {
            return Task.Run<List<Resource>>(async () =>
            {
                var fileSets = repository.Engines
                                         .OfType<_File>();
                var resources = new List<Resource>(512);
                foreach (var fileSet in fileSets)
                {
                    var output = await fileSet.GetResources();
                    resources.AddMany(output);
                }

                return resources;
            });
        }

        public static async Task<DeduplicateResult> Deduplicate(RepositoryRuntime repository)
        {
            var clearlyResource = await Find(repository.Repository);
            var dirtyResource   = await FindDirtyUsage(repository);
            var hashSet = clearlyResource.Select(x => x.ImageID)
                                         .ToHashSet();
            
            dirtyResource.ForEach(x =>
            {
                if (hashSet.Contains(x.ImageID))
                {
                    x.Usage = true;
                }
            });

            //
            // 所有已经试用的
            var usages = dirtyResource.Where(x => x.Usage)
                                      .Select(x => x.ImageID)
                                      .ToHashSet();
            
            //
            //
            var notFound = clearlyResource.Where(x => !usages.Contains(x.ImageID))
                                          .ToList();
            

            return new DeduplicateResult
            {
                Result   = dirtyResource,
                NotFound = notFound,
            };
        }

        public static IReadOnlyCollection<ResourceFinder> Finders { get; }
    }
}